/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.rocketmq.store.util;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;

/**
 * 在读取CommitLog时，虽然可以通过PageCache提高目标消息直接在物理内存中读取的命中率。
 * 但是由于CommitLog存放的是所有Topic的消息，在读取时是随机访问，所以仍会出现缺页中断问题，导致内存被频繁换入换出。
 * 为此，RocketMQ使用了mlock系统调用，将mmap调用后所占用的堆外内存锁定，变为常驻内存，进一步让目标消息更多的在内存中读取。
 *
 *
 * mlock这个方法是一个Native级别的调用，调用了标准C库的方法 mlock方法。在标准C中的实现是将锁住指定的内存区域避免被操作系统调到swap空间中，
 *
 *
 * 通过mmap建立的内存文件，在开始时只是建立一个映射关系，当读取相应区域的时候，第一次还是会去读磁盘，后续读写基本上与Page Cache交互。
 * 当读相对应页没有拿到数据的时候，系统将会产生一个缺页异常。madvise的作用是一次性先将一段数据读入到映射内存区域，这样就减少了缺页异常的产生， 不过mlock和madvise在windows下的C库没有
 *
 *
 * madvise系统调用有两个参数：地址指针、区间长度。madvise会向内核提供一个针对于进程虚拟地址区间的I/O建议，内核可能会采纳这个建议，进行预读。
 *
 *
 * RocketMQ使用net.java.dev.jna:jna:4.2.2，自己创建一个 LibC类继承Library
 *
 */
public interface LibC extends Library {
    LibC INSTANCE = (LibC) Native.loadLibrary(Platform.isWindows() ? "msvcrt" : "c", LibC.class);

    int MADV_WILLNEED = 3;
    int MADV_DONTNEED = 4;

    int MCL_CURRENT = 1;
    int MCL_FUTURE = 2;
    int MCL_ONFAULT = 4;

    /* sync memory asynchronously */
    int MS_ASYNC = 0x0001;
    /* invalidate mappings & caches */
    int MS_INVALIDATE = 0x0002;
    /* synchronous memory sync */
    int MS_SYNC = 0x0004;

    int mlock(Pointer var1, NativeLong var2);

    int munlock(Pointer var1, NativeLong var2);

    int madvise(Pointer var1, NativeLong var2, int var3);

    Pointer memset(Pointer p, int v, long len);

    int mlockall(int flags);

    int msync(Pointer p, NativeLong length, int flags);
}
